/*
 * io_buf.cpp
 *
 *  Created on: 2012-7-5
 *      Author: ThinkPad
 */

#include "io_buf.h"

io_buf::io_buf(void)
{
		buf_block_size = 0;
		buf_block_count = 0;
		total_count = 0;
		free_count=0;
}

io_buf::~io_buf(void)
{
		buf_lock.Lock();
		{
				while(buf_pool.size()>0)
				{
						buf_chunk * bc  = buf_pool.top();
						buf_pool.pop();

						if(bc != NULL)
						{
								bc->buffer = NULL;
								delete bc;
								bc = NULL;
						}
				}

				while(mem_pool.size()>0)
				{
						mem_chunk * mc = mem_pool.top();
						mem_pool.pop();

						if(mc != NULL && mc->mem != NULL)
						{
								mc->mem = NULL;
								delete mc->mem;
								delete mc;
								mc = NULL;
						}
				}

				buf_lock.Unlock();
		}
}

/*
*init buf pool,memory pool
*/
int io_buf::init_buf(int ichunk_count,int ichunk_size)
{
		buf_block_size = ichunk_size;
		buf_block_count = ichunk_count;
		return add_memory();
}
/*
*total buf count
*/
int io_buf::get_count()
{
		return total_count;
}
/*
*free buf count
*/
int io_buf::get_free_count()
{
    	return free_count;
}
/*
*add extern buf,100 chunk/per
*/
int io_buf::add_memory(void)
{
		char *mem_buf = new char[buf_block_size * buf_block_count];
		if(mem_buf == NULL)
		{
				return FAILURE;
		}

		memset(mem_buf,'\0',buf_block_size * buf_block_count);
		mem_chunk * mc = new mem_chunk();
		if(mc == NULL)
				return FAILURE;

		mc->len = buf_block_size * buf_block_count;
		mc->mem = mem_buf;
		mem_pool.push(mc);

		char *pbuf = mem_buf;
		for(int i = 0; i < buf_block_count; i++)
		{
				buf_chunk *newbuf = new buf_chunk();
				if(newbuf == NULL)
				{
						return FAILURE;
				}
				newbuf->index = i + total_count;
				newbuf->buffer = pbuf;
				newbuf->buf_len = buf_block_size;
				newbuf->size = 0;
				newbuf->offset = 0;
				newbuf->foffset = 0;
				newbuf->prev = NULL;
				newbuf->next = NULL;

				buf_pool.push(newbuf);
				total_count++;
				free_count++;

				pbuf += buf_block_size;
		}

		return SUCCESS;
}
/*
*alloc buf
*/
int io_buf::alloc_buf(buf_chunk **pbuf)
{
		buf_lock.Lock();
		{
				/*check is add extern buf*/
				if(free_count <= 0)
				{
						if(add_memory() != SUCCESS)
						{
								buf_lock.Unlock();
								return FAILURE;
						}
				}

				/*get a buf chunk from pool*/
				(*pbuf) = buf_pool.top();
				buf_pool.pop();
				free_count--;

				buf_lock.Unlock();
		}
		return SUCCESS;
}

/*
*free buf
*/
int io_buf::free_buf(buf_chunk *pbuf)
{
		if(pbuf!=_NULL)
		{
				buf_lock.Lock();
				{
						pbuf->offset = 0;
						pbuf->size = 0;
						memset(pbuf->buffer,'\0',pbuf->buf_len);
						pbuf->foffset = 0;
						pbuf->prev = NULL;
						pbuf->next = NULL;

						buf_pool.push(pbuf);
						free_count++;

						buf_lock.Unlock();
				}
				return SUCCESS;
		}
		else
		{
				return FAILURE;
		}
}
